package com.bom.boot.easy.core;

import cn.hutool.core.util.ReflectUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * <pre>
 *     {@link Result}: 结果集
 * </pre>
 *
 * @author 毛博
 * @date 2021-06-04
 * @time 10:37:37
 */
@Data
@Schema(description = "result")
public class Result<M> {
    @Schema(title = "状态码", description = "状态码 200为正常")
    private Integer code;
    @Schema(title = "消息", description = "请求成功或者请求失败的提示信息")
    private String msg;
    @Schema(title = "请求成功状态", description = "期望的操作正常执行")
    private Boolean success;
    @Schema(description = "列表,分页,统计,图标,详情,组合,下拉")
    private M data;
    @Schema(description = "列表数量")
    private Long total;
    @Schema(title = "额外数据,分页数据")
    private Map<String, Object> extra = new HashMap<>();
    public Result<M> total(Long total){
        this.setTotal(total);
        return this;
    }
    public Result<M> put(String key, Object value) {
        this.getExtra().put(key, value);
        return this;
    }

    public Result<M> putAll(Map<String, Object> map) {
        this.getExtra().putAll(map);
        return this;
    }

    public static <D> ResultBuilder<D> success(D data) {
        return Result.builder(true, data, 200, "operation success");
    }

    public static <D> ResultBuilder<D> success(D data, String msg) {
        return Result.builder(true, data, 200, msg);
    }


    public static <D> ResultBuilder<D> fail(String msg) {
        return Result.builder(false, null, 400, msg);
    }

    public static <D> ResultBuilder<D> fail() {
        return Result.builder(false, null, 400, "operation failed");
    }

    public static <D> ResultBuilder<D> fail(D data) {
        return Result.builder(false, data, 400, "operation failed");
    }

    public static <D> ResultBuilder<D> fail(Class<D> dClass, String msg) {
        return Result.builder(false, ReflectUtil.newInstanceIfPossible(dClass), 400, msg);
    }

    public static <D> ResultBuilder<D> fail(Class<D> dClass) {
        return fail(dClass, "operation failed");
    }

    public static <D> ResultBuilder<D> builder(Boolean success, D data, Integer code, String msg) {
        return new ResultBuilder<>(success, code, msg, data);
    }

    public static final class ResultBuilder<T> {
        private Integer code;
        private String msg;
        private T data;
        private Boolean success;

        public ResultBuilder(Boolean success, Integer code, String msg, T data) {
            this.success = success;
            this.code = code;
            this.msg = msg;
            this.data = data;
        }

        public ResultBuilder<T> code(Integer code) {
            this.code = code;
            return this;
        }

        public ResultBuilder<T> msg(String msg) {
            this.msg = msg;
            return this;
        }

        public ResultBuilder<T> success(Boolean success) {
            this.success = success;
            return this;
        }

        public Result<T> build() {
            Result<T> result = new Result<>();
            result.setCode(code);
            result.setMsg(msg);
            result.setData(data);
            result.setSuccess(success);
            return result;
        }
    }
}
